﻿using System;
using Xunit;
using Xunit.Should;

namespace Adjunct.Framework.Dependencies
{
	public class DependencyNodeSpec
	{
		private const string Level1A = "Level1A";
		private const string Level1B = "Level1B";
		private const string Level2A = "Level2A";
		private const string Level2B = "Level2B";

		[Fact]
		public void DoubleLayer()
		{
			DependencyNode t = DependencyNode.NewTerminator();
			DependencyNode l2a = t.AddUsage(Level2A);
			DependencyNode l1a = l2a.AddDependency(Level1A);
			t.IsUsedBy(Level2A).ShouldBeTrue();
			t.IsDirectlyUsedBy(Level2A).ShouldBeFalse();
			l1a.IsDirectlyUsedBy(Level2A).ShouldBeTrue();
			l1a.HasDirectDependencyOn(DependencyNode.TerminatorId).ShouldBeTrue();
			l2a.HasDependencyOn(DependencyNode.TerminatorId).ShouldBeTrue();
			l2a.HasDirectDependencyOn(Level1A).ShouldBeTrue();

			DependencyNode l1b = l2a.AddDependency(Level1B);
			l2a.HasDirectDependencyOn(Level1B).ShouldBeTrue();
			t.IsDirectlyUsedBy(Level1B).ShouldBeTrue();

			l1b.AddUsage(Level2B);
			t.IsUsedBy(Level2B).ShouldBeTrue();
			t.IsDirectlyUsedBy(Level2B).ShouldBeFalse();
		}

		[Fact]
		public void SingleLayer()
		{
			DependencyNode t = DependencyNode.NewTerminator();
			DependencyNode l1 = t.AddUsage(Level1A);
			t.IsUsedBy(Level1A).ShouldBeTrue();
			t.IsDirectlyUsedBy(Level1A).ShouldBeTrue();
			l1.HasDependencyOn(DependencyNode.TerminatorId).ShouldBeTrue();
			l1.HasDirectDependencyOn(DependencyNode.TerminatorId).ShouldBeTrue();
			l1.UsedBy.ShouldBeEmpty();
		}

		[Fact]
		public void Terminator()
		{
			DependencyNode t = DependencyNode.NewTerminator();
			t.Id.ShouldEqual(DependencyNode.TerminatorId);
			t.UsedBy.ShouldBeEmpty();
		}

		[Fact]
		public void TerminatorDependenciesThrow()
		{
			DependencyNode t = DependencyNode.NewTerminator();
			Exception exception = Assert.Throws<Exception>(() => t.AddDependency("anything"));
			exception.Message.ShouldEqual("You cannot add dependencies to the terminator");
		}
	}
}